/**
 * 
 */
package com.zhanggz.mypattern.proxy;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.io.FileUtils;

/**
 * 实现jdk原生的proxy，实现思路
 * 实现功能：通过Proxy的newProxyInstance返回代理对象
 * 1. 声明一段源码（动态产生代理）
 * 2. 编译源码（JDK Compiler API），产生新的类（代理类）
 * 3. 将这个类load到当前内存中，产生一个新的对象（代理对象）
 * 4. return 代理对象
 * 
 * @author alex
 * @Date Jun 27, 2015
 */
public class Proxy {

	public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
		String rt = "\n";
		String methodStr = "";
		for(Method m :infce.getMethods()){
			methodStr += 
			"public void "+ m.getName() +"() {" + rt +
			"	try{" + rt +
			"   Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() +"\");" + rt +
			"	h.invoke(this, md);" + rt +
			"	}catch(Exception e){e.printStackTrace();}" + rt +	
			"}";
		}
		String str = 
		"package com.zhanggz.mypattern.proxy;" + rt +
		"import com.zhanggz.mypattern.proxy.InvocationHandler;" + rt +
		"import java.lang.reflect.Method;" + rt +
		"public class $Proxy0 implements "+ infce.getName() +" {" + rt +
		"   private InvocationHandler h;" + rt +
		"	public $Proxy0(InvocationHandler h) {" + rt +
		"		this.h = h;" + rt +
		"	}" + rt +
		methodStr + rt +
		"}";
		
		//产生代理的java文件
		String fileName = System.getProperty("user.dir") + "/target/classes/com/zhanggz/mypattern/proxy/$Proxy0.java";
		File file = new File(fileName);
		FileUtils.writeStringToFile(file, str);
		
		//编译
		//得到当前系统的编译器
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		//文件管理者
		StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
		//获取文件
		Iterable untis = fileMgr.getJavaFileObjects(fileName);
		//编译任务
		CompilationTask task = compiler.getTask(null, fileMgr, null, null, null, untis);
		//进行编译
		task.call();
		fileMgr.close();
		
		//load到内存中
		ClassLoader cl = ClassLoader.getSystemClassLoader();
		Class c = cl.loadClass("com.zhanggz.mypattern.proxy.$Proxy0");
		
		//根据构造器构造对象
		Constructor ctr = c.getConstructor(InvocationHandler.class);
		return ctr.newInstance(h);
	}
}
